#include "recognize_at32mcu.h"

/* store read ID */
uint8_t   id_index[5] = {0};

/* AT32 mcu type table */
const uint64_t at32_mcu_id_table[] = {
  /* 403B mcu */
  0x0000000270050240,    /* AT32F403ZCT6      256KB       LQFP144 */
  0x0000000270050241,    /* AT32F403VCT6      256KB       LQFP100 */
  0x0000000270050242,    /* AT32F403RCT6      256KB       LQFP64 */
  0x0000000270050243,    /* AT32F403CCT6      256KB       LQFP48 */
  0x0000000270050344,    /* AT32F403ZGT6      1024KB      LQFP144 */
  0x0000000270050345,    /* AT32F403VGT6      1024KB      LQFP100 */
  0x0000000270050346,    /* AT32F403RGT6      1024KB      LQFP64 */
  0x0000000270050347,    /* AT32F403CGT6      1024KB      LQFP48 */
  0x00000002700502C8,    /* AT32F403ZET6      512KB       LQFP144 */
  0x00000002700502C9,    /* AT32F403VET6      512KB       LQFP100 */
  0x00000002700502CA,    /* AT32F403RET6      512KB       LQFP64 */
  0x00000002700502CB,    /* AT32F403CET6      512KB       LQFP48 */
  0x000000027005034C,    /* AT32F403CGU6      1024KB      QFN48 */
  0x00000002700502CD,    /* AT32F403CEU6      512KB       QFN48 */
  0x000000027005024E,    /* AT32F403CCU6      256KB       QFN48 */
  /* 413 mcu */
  0x0000000470030240,    /* AT32F413RCT7      256KB       LQFP64 */
  0x00000004700301C1,    /* AT32F413RBT7      128KB       LQFP64 */
  0x0000000470030242,    /* AT32F413CCT7      256KB       LQFP48 */
  0x00000004700301C3,    /* AT32F413CBT7      128KB       LQFP48 */
  0x0000000470030244,    /* AT32F413KCU7-4    256KB       QFN32 */
  0x00000004700301C5,    /* AT32F413KBU7-4    128KB       QFN32 */
  0x0000000470030106,    /* AT32F413C8T7      64KB        LQFN48 */
  0x0000000470030247,	   /* AT32F413CCU7	     256KB	     QFP48 */
  0x00000004700301C0,	   /* AT32F413CBU7    	 128KB	     QFP48 */
  /* 415 mcu */
  0x0000000570030240,    /* AT32F415RCT7      256KB       LQFP64 */
  0x0000000570030241,    /* AT32F415CCT7      256KB       LQFP48 */
  0x0000000570030242,    /* AT32F415KCU7-4    256KB       QFN32 */
  0x0000000570030243,    /* AT32F415RCT7-7    256KB       LQFP64 */
  0x00000005700301C4,    /* AT32F415RBT7      128KB       LQFP64 */
  0x00000005700301C5,    /* AT32F415CBT7      128KB       LQFP48 */
  0x00000005700301C6,    /* AT32F415KBU7-4    128KB       QFN32 */
  0x00000005700301C7,    /* AT32F415RBT7-7    128KB       LQFP64 */
  0x0000000570030108,    /* AT32F415R8T7      64KB        LQFP64 */
  0x0000000570030109,    /* AT32F415C8T7      64KB        LQFP48 */
  0x000000057003010B,    /* AT32F415R8T7-7    64KB        QFN32 */
  0x000000057003010A,    /* AT32F415K8U7-4    64KB        LQFP64 */
  0x00000005700301CD,	   /* AT32F415CBU7	     128KB	     QFN48 */
  0x000000057003024C,	   /* AT32F415CCU7	     256KB	     QFN48 */
  /* 403A mcu */
  0x0000000770050240,    /* AT32F403AVCT7     256KB       LQFP100 */
  0x0000000770050241,    /* AT32F403ARCT7     256KB       LQFP64 */
  0x0000000770050242,    /* AT32F403ACCT7     256KB       LQFP48 */
  0x0000000770050243,    /* AT32F403ACCU7     256KB       QFN48 */
  0x0000000770050344,    /* AT32F403AVGT7     1024KB      LQFP100 */
  0x0000000770050345,    /* AT32F403ARGT7     1024KB      LQFP64 */
  0x0000000770050346,    /* AT32F403ACGT7     1024KB      LQFP48 */
  0x0000000770050347,    /* AT32F403ACGU7     1024KB      QFN48 */
  0x00000007700502CD,	   /* AT32F403AVET7	   512KB	     LQFP100 */
  0x00000007700502CE,	   /* AT32F403ARET7	   512KB	     LQFP64 */
  0x00000007700503CF,	   /* AT32F403ACET7	   512KB	     LQFP48 */
  0x00000007700503D0,	   /* AT32F403ACEU7	   512KB	     QFN48 */
  /* 407 mcu */
  0x0000000870050249,    /* AT32F407VCT7      256KB       LQFP100 */
  0x000000087005024A,    /* AT32F407RCT7      256KB       LQFP64 */
  0x000000087005034B,    /* AT32F407VGT7      1024KB      LQFP100 */
  0x000000087005034C,    /* AT32F407RGT7      1024KB      LQFP64 */
  0x00000008700502D1,	   /* AT32F407VET7	     512KB     	 LQFP100 */
  0x00000008700502D2,	   /* AT32F407RET7	     512KB	     LQFP64 */
  /* 421 mcu */
  0x0000000950020100,    /* AT32F421C8T7      64KB */
  0x0000000950020101,    /* AT32F421K8T7      64KB         LQFP32 */
  0x0000000950020102,    /* AT32F421K8U7      64KB         QFN32 */
  0x0000000950020103,    /* AT32F421K8U7-4    64KB         Q */
  0x0000000950020104,    /* AT32F421F8U7      64KB         QFN20 */
  0x0000000950020105,    /* AT32F421F8P7      64KB         TSSOP20 */
  0x0000000950020086,    /* AT32F421C6T7      32KB */
  0x0000000950020087,    /* AT32F421K6T7      32KB         LQFP32 */
  0x0000000950020088,    /* AT32F421K6U7      32KB         QFN32 */
  0x0000000950020089,    /* AT32F421K6U7-4    32KB         Q */
  0x000000095002008A,    /* AT32F421F6U7      32KB         QFN20 */
  0x000000095002008B,    /* AT32F421F6P7      32KB         TSSOP20 */
  0x000000095001000C,    /* AT32F421C4T7      16KB */
  0x000000095001000D,    /* AT32F421K4T7      16KB         LQFP32 */
  0x000000095001000E,    /* AT32F421K4U7      16KB         QFN32 */
  0x000000095001000F,    /* AT32F421K4U7-4    16KB         Q */
  0x0000000950010010,    /* AT32F421F4U7      16KB         QFN20 */
  0x0000000950010011,    /* AT32F421F4P7      16KB         TSSOP20 */
  0x0000000950020112,    /* AT32F421G8U7      64KB         QFN28 */
  0x0000000950020093,    /* AT32F421G6U7      32KB         QFN28 */
  0x0000000950010014,    /* AT32F421G4U7      16KB         QFN28 */
  0x0000000950020115,    /* AT32F421PF8P7     64KB         TSSOP20 */
  0x0000000950010016,    /* AT32F421PF4P7     16KB         TSSOP20 */
  0x0000000950020117,    /* AT32F421C8W       64KB */
  0x00000009D0020100,    /* AT32F421C8W-YY    64KB */
  /* 435/437 mcu */
  0x0000000D70084540,    /* AT32F435ZMT7      4032KB        LQFP144 */
  0x0000000D70083341,    /* AT32F435ZGT7      1024KB        LQFP144 */
  0x0000000D70083242,    /* AT32F435ZCT7      256KB         LQFP144 */
  0x0000000D70084543,    /* AT32F435VMT7      4032KB        LQFP100 */
  0x0000000D70083344,    /* AT32F435VGT7      1024KB        LQFP144 */
  0x0000000D70083245,    /* AT32F435VCT7      256KB         LQFP100 */
  0x0000000D70084546,    /* AT32F435RMT7      4032KB        LQFP64 */
  0x0000000D70083347,    /* AT32F435RGT7      1024KB        LQFP64 */
  0x0000000D70083248,    /* AT32F435RCT7      256KB         LQFP64 */
  0x0000000D70084549,    /* AT32F435CMT7      4032KB        LQFP48 */
  0x0000000D7008334A,    /* AT32F435CGT7      1024KB        LQFP48 */
  0x0000000D7008324B,    /* AT32F435CCT7      256KB         LQFP48 */
  0x0000000D7008454C,    /* AT32F435CMU7      4032KB        QFN48 */
  0x0000000D7008334D,    /* AT32F435CGU7      1024KB        QFN48 */
  0x0000000D7008324E,    /* AT32F435CCU7      256KB         QFN48 */
  0x0000000E7008454F,    /* AT32F437ZMT7      4032KB        LQFP144 */
  0x0000000E70083350,    /* AT32F437ZGT7      1024KB        LQFP144 */
  0x0000000E70083251,    /* AT32F437ZCT7      256KB         LQFP144 */
  0x0000000E70084552,    /* AT32F437VMT7      4032KB        LQFP100 */
  0x0000000E70083353,    /* AT32F437VGT7      1024KB        LQFP100 */
  0x0000000E70083254,    /* AT32F437VCT7      256KB         LQFP100 */
  0x0000000E70084555,    /* AT32F437RMT7      4032KB        LQFP64 */
  0x0000000E70083356,    /* AT32F437RGT7      1024KB        LQFP64 */
  0x0000000E70083257,    /* AT32F437RCT7      256KB         LQFP64 */
  /* 423 mcu */
  0x00000012700A3240,    /* AT32F423VCT7      256KB         LQFP100 */
  0x00000012700A21C1,    /* AT32F423VBT7      128KB         LQFP100 */
  0x0000001270032102,    /* AT32F423V8T7      64KB          LQFP100 */
  0x00000012700A3243,    /* AT32F423RCT7      256KB         LQFP64 */
  0x00000012700A21C4,    /* AT32F423RBT7      128KB         LQFP64 */
  0x0000001270032105,    /* AT32F423R8T7      64KB          LQFP64 */
  0x00000012700A3246,    /* AT32F423RCT7-7    256KB         LQFP64 */
  0x00000012700A21C7,    /* AT32F423RBT7-7    128KB         LQFP64 */
  0x0000001270032108,    /* AT32F423R8T7-7    64KB          LQFP64 */
  0x00000012700A3249,    /* AT32F423CCT7      256KB         LQFP48 */
  0x00000012700A21CA,    /* AT32F423CBT7      128KB         LQFP48 */
  0x000000127003210B,    /* AT32F423C8T7      64KB          LQFP48 */
  0x00000012700A324C,    /* AT32F423CCU7      256KB         QFN48 */
  0x00000012700A21CD,    /* AT32F423CBU7      128KB         QFN48 */
  0x000000127003210E,    /* AT32F423C8U7      64KB          QFN48 */
  0x00000012700A3250,    /* AT32F423TCU7      256KB         QFN36 */
  0x00000012700A21D1,    /* AT32F423TBU7      128KB         QFN36 */
  0x0000001270032112,    /* AT32F423T8U7      64KB          QFN36 */
  0x00000012700A3253,    /* AT32F423KCU7-4    256KB         QFN32 */
  0x00000012700A21D4,    /* AT32F423KBU7-4     128KB        QFN32 */
  0x0000001270032115,    /* AT32F423K8U7-4     64KB         QFN32 */
  /* 425 mcu */
  0x0000000F50092100,    /* AT32F425R8T7      64KB         64LQFP (10 x10) */
  0x0000000F50092081,    /* AT32F425R6T7      32KB         64LQFP (10 x10) */
  0x0000000F50092103,    /* AT32F425R8T7-7    64KB         64LQFP (7 x 7) */
  0x0000000F50092084,    /* AT32F425R6T7-7    32KB         64LQFP (7 x 7) */
  0x0000000F50092106,    /* AT32F425C8T7      64KB         48LQFP */
  0x0000000F50092087,    /* AT32F425C6T7      32KB         48LQFP */
  0x0000000F50092109,    /* AT32F425C8U7      64KB         48QFN */
  0x0000000F5009208A,    /* AT32F425C6U7      32KB         48QFN */
  0x0000000F5009210C,    /* AT32F425K8T7      64KB         32LQFP */
  0x0000000F5009208D,    /* AT32F425K6T7      32KB         32LQFP */
  0x0000000F5009210F,    /* AT32F425K8U7-4    64KB         32QFN */
  0x0000000F50092090,    /* AT32F425K6U7-4    32KB         32QFN */
  0x0000000F50092112,    /* AT32F425F8P7      64KB         20TSSOP */
  0x0000000F50092093,    /* AT32F425F6P7      32KB         20TSSOP */
  /* A403A mcu */
  0x0000001870050340,    /* AT32A403AVGT7     1024KB       LQFP100 */
  0x00000018700502C1,    /* AT32A403AVET7     512KB        LQFP100 */
  0x0000001870050242,    /* AT32A403AVCT7     256KB        LQFP100 */
  0x0000001870050343,    /* AT32A403ARGT7     1024KB       LQFP64 */
  0x00000018700502C4,    /* AT32A403ARET7     512KB        LQFP64 */
  0x0000001870050245,    /* AT32A403ARCT7     256KB        LQFP64 */
  0x0000001870050346,    /* AT32A403ACGT7     1024KB       LQFP48 */
  0x00000018700502C7,    /* AT32A403ACET7     512KB        LQFP48 */
  0x0000001870050248,    /* AT32A403ACCT7     256KB        LQFP48 */
  0x0000001870050349,    /* AT32A403ACGU7     1024KB       QFN48 */
  0x00000018700502CA,    /* AT32A403ACEU7     512KB        QFN48 */
  0x000000187005024B,    /* AT32A403ACCU7     256KB        QFN48 */
  /* WB415 mcu */
  0x0000001170030250,    /* AT32WB415CCU7-7     256KB      QFN48_7x7 */

};

/* arm cortex type table */
const uint32_t mcu_cortex_id_table[] = {
  0x410CC200,            /*!< Cortex-M0-r0p0 */
  0x410CC600,            /*!< Cortex-M0+-r0p0 */
  0x410CC210,            /*!< Cortex-M1-r0p1 */
  0x410CC211,            /*!< Cortex-M1-r0p1 */
  0x411CC210,            /*!< Cortex-M1-r1p0 */
  0x410FC230,            /*!< Cortex-M3-r0p0 */
  0x410FC231,            /*!< Cortex-M3-r1p0 */
  0x411FC231,            /*!< Cortex-M3-r1p1 */
  0x412FC230,            /*!< Cortex-M3-r2p0 */
  0x412FC231,            /*!< Cortex-M3-r2p1 */
  0x410FC240,            /*!< Cortex-M4-r0p0 */
  0x410FC241,            /*!< Cortex-M4-r0p1 */
};


/**
  * @brief  read id and identify function.
  * @param  none
  * @retval device type
  */
uint16_t recognize_id(void)
{
  uint64_t at_device_id = 0;
  uint16_t index = 0;
  uint16_t device_type_index = 0;

  /* read pid/uid */
  id_index[0] = *(int*)DEVICE_ID_ADDR1;
  id_index[1] = *(int*)(DEVICE_ID_ADDR2+3);
  id_index[2] = *(int*)(DEVICE_ID_ADDR2+2);
  id_index[3] = *(int*)(DEVICE_ID_ADDR2+1);
  id_index[4] = *(int*)(DEVICE_ID_ADDR2+0);

  /* combination pid/uid */
  at_device_id = ((uint64_t)id_index[0] << 32) | ((uint64_t)id_index[1] << 24) | ((uint64_t)id_index[2] << 16) | ((uint64_t)id_index[3] << 8)|((uint64_t)id_index[4] << 0);

  /* identify actual device type */
  for(index = 0; index < sizeof(at32_mcu_id_table) / sizeof(at32_mcu_id_table[0]); index++)
  {
    if(at_device_id == at32_mcu_id_table[index])
    {
      switch(id_index[0])
      {
        case PROJECT_ID_403:
          device_type_index = AT32F403_DEVICE;
          break;

        case PROJECT_ID_413:
          device_type_index = AT32F413_DEVICE;
          break;

        case PROJECT_ID_415:
          device_type_index = AT32F415_DEVICE;
          break;

        case PROJECT_ID_403A:
          device_type_index = AT32F403A_DEVICE;
          break;

        case PROJECT_ID_407:
          device_type_index = AT32F407_DEVICE;
          break;

        case PROJECT_ID_421:
          device_type_index = AT32F421_DEVICE;
          break;

        case PROJECT_ID_423:
          device_type_index = AT32F423_DEVICE;
          break;

        case PROJECT_ID_425:
          device_type_index = AT32F425_DEVICE;
          break;

        case PROJECT_ID_435:
          device_type_index = AT32F435_DEVICE;
          break;

        case PROJECT_ID_437:
          device_type_index = AT32F437_DEVICE;
          break;

        case PROJECT_ID_A403A:
          device_type_index = AT32A403A_DEVICE;
          break;

        case PROJECT_ID_WB415:
          device_type_index = AT32WB415_DEVICE;
          break;

        default:
          device_type_index = FALSE;
          break;
      }
     return device_type_index;
    }
  }
  return FALSE;
}

/**
  * @brief  read cortex and identify function.
  * @param  none
  * @retval cortex type
  */
uint8_t recognize_cortex(void)
{
  uint32_t  cortex_id_index = 0;
  uint8_t  index = 0;
  /* read cortex type */
  cortex_id_index = *(uint32_t *)0xE000ED00;

  /* identify actual cortex type */
  for(index = 0; index < (sizeof(mcu_cortex_id_table) / sizeof(mcu_cortex_id_table[0])); index++)
  {
    if((cortex_id_index == mcu_cortex_id_table[0]) || (cortex_id_index == mcu_cortex_id_table[1]))
      return Cortex_M0;
    if((cortex_id_index == mcu_cortex_id_table[2]) || (cortex_id_index == mcu_cortex_id_table[3]) || (cortex_id_index == mcu_cortex_id_table[4]))
      return Cortex_M1;
    if((cortex_id_index == mcu_cortex_id_table[5]) || (cortex_id_index == mcu_cortex_id_table[6]) || (cortex_id_index == mcu_cortex_id_table[7]) || (cortex_id_index == mcu_cortex_id_table[8]) || (cortex_id_index == mcu_cortex_id_table[9]))
      return Cortex_M3;
    if((cortex_id_index == mcu_cortex_id_table[10]) || (cortex_id_index == mcu_cortex_id_table[11]))
      return Cortex_M4;
  }
  return FALSE;
}

void recognize_mcu(void)
{

  volatile uint16_t mcu_index = 0;
  volatile uint8_t cortex_index = 0;

  printf("at32 mcu recognize test!\r\n");

  /* recongnize mcu type */
  mcu_index = recognize_id();
  switch(mcu_index)
  {
    case AT32F403_DEVICE:
      printf("it's at32f403 mcu!\r\n");
      break;
    case AT32F413_DEVICE:
      printf("it's at32f413 mcu!\r\n");
      break;
    case AT32F415_DEVICE:
      printf("it's at32f415 mcu!\r\n");
      break;
    case AT32F403A_DEVICE:
      printf("it's at32f403a mcu!\r\n");
      break;
    case AT32F407_DEVICE:
      printf("it's at32f407 mcu!\r\n");
      break;
    case AT32F421_DEVICE:
      printf("it's at32f421 mcu!\r\n");
      break;
    case AT32F423_DEVICE:
      printf("it's at32f423 mcu!\r\n");
      break;
    case AT32F425_DEVICE:
      printf("it's at32f425 mcu!\r\n");
      break;
    case AT32F435_DEVICE:
      printf("it's at32f435 mcu!\r\n");
      break;
    case AT32F437_DEVICE:
      printf("it's at32f437 mcu!\r\n");
      break;
    case AT32A403A_DEVICE:
      printf("it's at32a403a mcu!\r\n");
      break;
    case AT32WB415_DEVICE:
      printf("it's at32wb415 mcu!\r\n");
      break;

    default:
      printf("no adaptation mcu type!\r\n");
      break;
  }

  /* recongnize cortex type */
  cortex_index = recognize_cortex();
  switch(cortex_index)
  {
    case Cortex_M0:
      printf("cortex type is cortex-m0!\r\n");
      break;
    case Cortex_M1:
      printf("cortex type is cortex-m1!\r\n");
      break;
    case Cortex_M3:
      printf("cortex type is cortex-m3!\r\n");
      break;
    case Cortex_M4:
      printf("cortex type is cortex-m4!\r\n");
      break;
    default:
      printf("no adaptation cortex type!\r\n");
      break;
  }
}

